/*----------------------------------------------------------------------------
 * Copyright (c) <2016-2018>, <Huawei Technologies Co., Ltd>
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice, this list of
 * conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
 * of conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
 * to endorse or promote products derived from this software without specific prior written
 * permission.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *---------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
 * Notice of Export Control Law
 * ===============================================
 * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
 * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
 * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
 * applicable export control laws and regulations.
 *---------------------------------------------------------------------------*/
#ifdef WITH_LWIP

#include <stdio.h>
#include <string.h>
#include "csg_sdk_hal.h"
#include "lwip/init.h"
#include "lwip/tcpip.h"
#include "netif/etharp.h"
#include "ethernetif.h"
#include "lwip/tcpip.h"

#include "csg_xec.h"
//receive in task
#define RECV_THREAD_EN    1
//receive in INT
#define RECV_INT_EN       0

extern struct     netif gnetif;

extern uint32_t  ETH_DMADESC_Index;
extern  uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE];
extern  uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE];
uint8_t MyMac[6]={0x00, 0x2b, 0x20, 0x21, 0x03, 0x23};

typedef uint32_t u32 ;
typedef uint16_t u16;
typedef uint8_t u8;

#define netifINTERFACE_TASK_STACK_SIZE              ( 4096u )
#define netifINTERFACE_TASK_PRIORITY                ( 6u   )
/* The time to block waiting for input. */
#define TIME_WAITING_FOR_INPUT                      ( 500u )

static sys_sem_t s_xSemaphore;


static struct pbuf * low_level_input(struct netif *netif);

err_t ethernetif_input2(struct netif *netif)
{
	err_t err;
	struct pbuf *p;
	p=low_level_input(netif);
	if(p==NULL) return ERR_MEM;
	err=netif->input(p, netif);
	if(err!=ERR_OK)
	{
		LWIP_DEBUGF(NETIF_DEBUG,("ethernetif_input: IP input error\n"));
		pbuf_free(p);
		p = NULL;
	}

	return err;
}

void XEC_IRQHandler(void)
{
	uint32_t length;

	//printf("XEC_IRQHandler\r\n");
	if(ETH_IOC_CHX->IOC_CHX_IT_STATUS & (0x1<<16))
	{
		//while(DMARxDscrTab[0].COMM & (0x1<<24));
		ETH_IOC_CHX->IOC_CHX_IT_STATUS &= ~(0x1<<16);
		
   #if RECV_INT_EN > 0	
		ethernetif_input2(&gnetif);
   #endif		
   #if RECV_THREAD_EN > 0		
		sys_sem_signal(&s_xSemaphore);
   #endif
	}

}

static void eth_thread(void *arg)
{
    while (1)
    {
        sys_arch_sem_wait(&s_xSemaphore, 0);	//timeout_forever	
        //sys_arch_sem_wait(&s_xSemaphore, TIME_WAITING_FOR_INPUT);
		
        ethernetif_input2(arg);
    }
}


static err_t low_level_init(struct netif *netif)
{
#ifdef CHECKSUM_BY_HARDWARE
	int i;
#endif
    struct ethernetif*  ethernetif= netif->state;
	netif->hwaddr_len = ETHARP_HWADDR_LEN; //设置MAC地址长度,为6个字节
    netif->hwaddr[0]=MyMac[0];
	netif->hwaddr[1]=MyMac[1];
	netif->hwaddr[2]=MyMac[2];
	netif->hwaddr[3]=MyMac[3];
	netif->hwaddr[4]=MyMac[4];
	netif->hwaddr[5]=MyMac[5];
	netif->mtu=1500; //最大允许传输单元,允许该网卡广播和ARP功能

	netif->flags = NETIF_FLAG_BROADCAST|NETIF_FLAG_ETHARP|NETIF_FLAG_LINK_UP;

    ETH_Init();
    ETH_DMARxDescChainInit();
    ETH_DMATxDescChainInit();
    IOC_CHx_Interrupt_Enable(ETH_IOC_CHX,RX_PKT_INTR_EN);

#if RECV_THREAD_EN > 0
    if (ERR_OK != sys_sem_new(&s_xSemaphore, 0))
    {
        return -1;
    }
    /* create the task that handles the ETH_MAC */
	
    printf("create Eth_if thread\r\n");
    sys_thread_new((char *)"Eth_if", eth_thread, netif, netifINTERFACE_TASK_STACK_SIZE, netifINTERFACE_TASK_PRIORITY);
#endif
	
    ETH_IOCRxCmd(ENABLE);
    printf("low_level_init\r\n");

	return ERR_OK;
}

static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
	u8 res;
	struct pbuf *q;
	int templen = 0;

	//printf("low_level_output\r\n");
	// u8 *buffer=(u8 *)ETH_GetCurrentTxBuffer();
	for(q=p;q!=NULL;q=q->next)
	{
		memcpy((uint8_t *)&Tx_Buff[ETH_DMADESC_Index][templen], q->payload, q->len);
		templen=templen+q->len;
	}

	res=ETH_Tx_Packet(templen);
	if(res==0)return 0;//返回错误状态
	return 0;
}

static struct pbuf * low_level_input(struct netif *netif)
{
	struct pbuf *p, *q;
	u16_t len;
	int templen =0;
	FrameTypeDef frame;
	u8 *buffer;
	/////YHF
	u16_t i,j;
	/////YHF

	//printf("low_level_input\r\n");
	// printf("\r\nReceive ETH message:\r\n");
	p = NULL;
	frame=ETH_Rx_Packet();
	len=frame.length;//得到包大小
	buffer=(u8 *)frame.buffer;//得到包数据地址

	p=pbuf_alloc(PBUF_RAW,len,PBUF_POOL);//pbufs内存池分配pbuf
	
	if(p!=NULL)
	{
		j=0;
		for(q=p;q!=NULL;q=q->next)
		{
			/////YHF
			// printf("\r\ndata packet %d is:\r\n",j);
			// j++;
			/////YHF
			memcpy((u8_t*)q->payload,(u8_t*)&buffer[templen], q->len);
			/////YHF
			// for(i=0;i<(q->len);i++)
			// {
			// 	printf(" 0x%02X",(u8_t*)buffer[templen+i]);
			// }
			// printf("\r\n");
			/////YHF
			templen=templen+q->len;
			
		}		
	}

	return p;
}


struct ethernet_api g_eth_api = {
    .init     = low_level_init,
    .output   = low_level_output,
    .input    = low_level_input,
};
#endif


